#ifndef XTCP_H
#define XTCP_H
#include "xnet_tiny.h"
#include "xnet_err.h"
#include "xtcp_buffer.h"

// TCP

#define XTCP_CFG_MAX_TCP 40
#define XTCP_CFG_RTX_BUF_SIZE 1024

#define XTCP_KIND_END 0
#define XTCP_KIND_MSS 2
#define XTCP_MSS_DEFAULT 1460

// tcp控制块

// tcp回调函数的状态
typedef enum _xtcp_conn_state_t
{
    XTCP_CONN_CONNECTED,
    XTCP_CONN_DATA_RECV,
    XTCP_CONN_CLOSED,
} xtcp_conn_state_t;

typedef struct _xtcp_t xtcp_t;
typedef xnet_err_t (*xtcp_handler_t)(xtcp_t *tcp, xtcp_conn_state_t event);

// tcp控制块的状态，具体含义见tcp状态机
typedef enum _xtcp_state_t
{
    XTCP_STATE_FREE = 0,
    XTCP_STATE_CLOSED,
    XTCP_STATE_LISTEN,
    XTCP_STATE_SYNC_RECVD, // 已经接受到syn，发送了ack syn之后的状态
    XTCP_STATE_ESTABLISHED,
    XTCP_STATE_FIN_WAIT_1,
    XTCP_STATE_FIN_WAIT_2,
    XTCP_STATE_CLOSING,
    XTCP_STATE_TIMED_WAIT,
    XTCP_STATE_CLOSE_WAIT,
    XTCP_STATE_LAST_ACK,
} xtcp_state_t;

struct _xtcp_t
{
    xtcp_state_t state;
    uint16_t local_port, remote_port;
    xipaddr_t remote_ip;
    uint32_t next_seq;            // 下一个包发送的序列号
    uint32_t next_ack;            // 下一个包发送的确认号
    uint32_t unacked_seq;         // 未被确认的序列号
    uint16_t remote_mss;          // 对方的mss,不含选项区
    uint16_t remote_win;          // 对方的窗口大小
    xtcp_handler_t handler;       // 事件处理回调
    xtcp_buffer_t rx_buf, tx_buf; // 收发缓冲区
};

xtcp_t *xtcp_open(xtcp_handler_t handler);
xnet_err_t xtcp_bind(xtcp_t *tcp, uint16_t local_port);
xnet_err_t xtcp_listen(xtcp_t *tcp);
xnet_err_t xtcp_close(xtcp_t *tcp);

// tcp包头

// 标志位
#define XTCP_FLAG_FIN (1 << 0)
#define XTCP_FLAG_SYN (1 << 1)
#define XTCP_FLAG_RST (1 << 2)
#define XTCP_FLAG_ACK (1 << 4)

#pragma(1)
typedef struct _xtcp_hdr_t
{
    uint16_t src_port, dest_port;
    uint32_t seq; // 序列号
    uint32_t ack; // 确认号

    union
    {
        struct
        {
            uint16_t flag : 6;
            uint16_t reserved : 6;
            uint16_t hdr_len : 4;
        };
        uint16_t all;
    } hdr_flags;
    uint16_t window;     // 窗口大小
    uint16_t checksum;   // 校验和
    uint16_t urgent_ptr; // 紧急指针

} xtcp_hdr_t;

xnet_err_t tcp_close(xtcp_t *tcp);

xnet_err_t tcp_send(xtcp_t *tcp, uint8_t flags);

void xtcp_init(void);
void xtcp_in(xipaddr_t *remote_ip, xnet_packet_t *packet);

#pragma()

#endif
